package com.hangim.pce.common.search.service.impl;

import com.hangim.pce.common.search.domain.ESDisease;
import com.hangim.pce.common.search.domain.ESDrug;
import com.hangim.pce.common.search.domain.ESElement;
import com.hangim.pce.common.search.domain.ESSymptom;
import com.hangim.pce.common.search.enums.ESEntityType;
import com.hangim.pce.common.search.repository.ESDiseaseRepository;
import com.hangim.pce.common.search.repository.ESDrugRepository;
import com.hangim.pce.common.search.repository.ESElementRepository;
import com.hangim.pce.common.search.repository.ESSymptomRepository;
import com.hangim.pce.common.search.service.ESSearchService;
import com.hangim.pce.common.web.WebRequestContext;
import com.hangim.pce.model.BaseDrug;
import com.hangim.pce.model.BaseElement;
import com.hangim.pce.model.SysDisease;
import com.hangim.pce.model.SysSymptom;
import com.hangim.pce.service.BaseDrugService;
import com.hangim.pce.service.BaseElementService;
import com.hangim.pce.service.SysDiseaseService;
import com.hangim.pce.service.SysSymptomService;
import com.github.pig.common.util.StringUtils;
import com.google.common.collect.Lists;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author SunLearning
 * @see ESSearchService
 */
@Service
public class ESSearchServiceImpl extends BaseElasticSearchServiceImpl implements ESSearchService {
    @Autowired
    private ESDiseaseRepository esDiseaseRepository;

    @Autowired
    private ESDrugRepository esDrugRepository;

    @Autowired
    private ESElementRepository esElementRepository;

    @Autowired
    private ESSymptomRepository esSymptomRepository;

    @Autowired
    private BaseDrugService baseDrugService;

    @Autowired
    private SysDiseaseService sysDiseaseService;

    @Autowired
    private BaseElementService baseElementService;

    @Autowired
    private SysSymptomService sysSymptomService;


    /**
     * @see ESSearchService#search(WebRequestContext context, String typeName)
     */
    @Override
    public Page search(WebRequestContext context, String typeName) {
        Pageable pageable = context.getPageable();
        String q = context.getQ();

        if (ESEntityType.DISEASE.getCode().equalsIgnoreCase(typeName)) {
            return searchDisease(q, pageable);

        } else if (ESEntityType.DRUG.getCode().equalsIgnoreCase(typeName)) {
            return searchDrug(q, pageable);

        } else if (ESEntityType.SYMPTOM.getCode().equalsIgnoreCase(typeName)) {
            return searchSymptom(q, pageable);

        } else if (ESEntityType.ELEMENT.getCode().equalsIgnoreCase(typeName)) {
            return searchElement(q, pageable);

        } else {
            return formatSearchResult(Lists.newArrayList(), pageable.getPageNumber(), pageable.getPageSize(),
                    pageable.getSort(), 0L);
        }
    }

    /**
     * 搜索疾病
     *
     * @param q        搜索关键字
     * @param pageable spring data 的分页实例
     * @return Page
     */
    private Page searchDisease(String q, Pageable pageable) {
        List<SysDisease> resultList = Lists.newArrayList();

        // 在 ElasticSearch 中搜索数据
        Page<ESDisease> searchResult = esDiseaseRepository.findDiseaseForPage(q, pageable);

        // 循环搜索结果，从数据库中获取完整数据
        for (ESDisease esDisease : searchResult.getContent()) {
            SysDisease sysDisease = sysDiseaseService.selectById(esDisease.getId());
            if (sysDisease != null) {
                resultList.add(sysDisease);
            }
        }

        // 构建返回的数据
        return formatSearchResult(resultList, searchResult.getNumber(), pageable.getPageSize(), searchResult.getSort(),
                searchResult.getTotalElements());
    }

    /**
     * 搜索药品
     *
     * @param q        搜索关键字
     * @param pageable spring data 的分页实例
     * @return Page
     */
    private Page searchDrug(String q, Pageable pageable) {
        List<BaseDrug> resultList = Lists.newArrayList();

        // 在 ElasticSearch 中搜索数据
        Page<ESDrug> searchResult = null;
        if (StringUtils.isNotEmpty(q)) {


            // 声明where条件
            BoolQueryBuilder qbs = QueryBuilders.boolQuery();

/*
            //此处使用模糊匹配查询 类比数据库中 like
            QueryBuilder qb1 = QueryBuilders.matchPhraseQuery("name", q);
            BoolQueryBuilder bqb1 = QueryBuilders.boolQuery().must(qb1);
            qbs.must(bqb1);
            */
            //主查询
            qbs.must(
                    QueryBuilders.boolQuery()
                            .should(QueryBuilders.matchPhraseQuery("name", q))
                            .should(QueryBuilders.wildcardQuery("spell", "*"+q+"*"))
                            .should(QueryBuilders.matchPhraseQuery("name_alias", q))
            );

            searchResult = esDrugRepository.search(qbs, pageable);

        } else {
            searchResult = esDrugRepository.findAll(pageable);
        }


        // 循环搜索结果，从数据库中获取完整数据
        for (ESDrug esDrug : searchResult.getContent()) {
            BaseDrug baseDrug = baseDrugService.selectById(esDrug.getId());
            if (baseDrug != null) {
                resultList.add(baseDrug);
            }
        }

        // 构建返回的数据
        return formatSearchResult(resultList, searchResult.getNumber(), pageable.getPageSize(), searchResult.getSort(),
                searchResult.getTotalElements());
    }

    /**
     * 搜索症状
     *
     * @param q        搜索关键字
     * @param pageable spring data 的分页实例
     * @return Page
     */
    private Page searchSymptom(String q, Pageable pageable) {
        List<SysSymptom> resultList = Lists.newArrayList();

        // 在 ElasticSearch 中搜索数据
        Page<ESSymptom> searchResult = esSymptomRepository.findSymptomForPage(q, pageable);

        // 循环搜索结果，从数据库中获取完整数据
        for (ESSymptom esSymptom : searchResult.getContent()) {
            SysSymptom sysSymptom = sysSymptomService.selectById(esSymptom.getId());
            if (sysSymptom != null) {
                resultList.add(sysSymptom);
            }
        }

        // 构建返回的数据
        return formatSearchResult(resultList, searchResult.getNumber(), pageable.getPageSize(), searchResult.getSort(),
                searchResult.getTotalElements());
    }

    /**
     * 搜索成分
     *
     * @param q        搜索关键字
     * @param pageable spring data 的分页实例
     * @return Page
     */
    private Page searchElement(String q, Pageable pageable) {
        List<BaseElement> resultList = Lists.newArrayList();

        // 在 ElasticSearch 中搜索数据
        Page<ESElement> searchResult = esElementRepository.findElementForPage(q, pageable);

        // 循环搜索结果，从数据库中获取完整数据
        for (ESElement esElement : searchResult.getContent()) {
            BaseElement element = baseElementService.selectById(esElement.getId());
            if (element != null) {
                resultList.add(element);
            }
        }

        // 构建返回的数据
        return formatSearchResult(resultList, searchResult.getNumber(), pageable.getPageSize(), searchResult.getSort(),
                searchResult.getTotalElements());
    }

    private Page formatSearchResult(List resultList, int number, int size, Sort sort, Long totalElements) {
        Pageable resultPageable = new PageRequest(number, size, sort);
        return new PageImpl(resultList, resultPageable, totalElements);
    }


}
